BASLR
roy g biv / defjam
comment ;) BASLR by roy g biv It's a tool, not a virus. --- to build this thing: tasm ---- tasm32 /ml /m3 baslr tlink32 /B:400000 /x baslr,,,import32 Code is not self-modifying, so no need to alter section attributes --- (; .586 ;rdtsc .model flat extern GetCommandLineW:proc extern CharNextW:proc extern WriteFile:proc extern CloseHandle:proc extern ExitProcess:proc extern CreateFileW:proc extern ReadFile:proc extern SetFilePointer:proc extern MessageBoxA:proc .data include baslr.inc baslr_begin label near push '!bgr' ;----------------------------------------------------------------------------- ;recover ntdll image base ;----------------------------------------------------------------------------- mov eax, dword ptr fs:[tebProcessEnvironmentBlock] mov eax, dword ptr [eax + pebLdr] mov eax, dword ptr [eax + ldrInLoadOrderModuleList] mov ebx, dword ptr [eax + mlDllBase] mov esi, dword ptr [ebx + e_lfanew] call skip_apis ;----------------------------------------------------------------------------- ;API CRC table, null terminated ;----------------------------------------------------------------------------- dd 0E1E08AA1h ;KiUserExceptionDispatcher dd 0AF7D682Dh ;NtAllocateVirtualMemory dd 004D1E941h ;NtProtectVirtualMemory dd 0E6AE7AC8h ;NtQueryVirtualMemory apis_end label near dd 0 ;----------------------------------------------------------------------------- ;VirtualAlloc(address, size, type, prot) -> NtAllocateVirtualMemory(-1, &address, 0, &size, type, prot) ;----------------------------------------------------------------------------- VirtualAlloc proc near push dword ptr [esp + 10h] push dword ptr [esp + 10h] lea eax, dword ptr [esp + 10h] push eax push 0 lea eax, dword ptr [esp + 14h] push eax push -1 xVirtualAlloc label near mov eax, '!bgr' call eax pop ecx pop eax push ecx ret 0ch VirtualAlloc endp ;----------------------------------------------------------------------------- ;VirtualProtect(address, size, newprot, oldprot) -> NtProtectVirtualMemory(-1, &address, &size, newprot, oldprot) ;----------------------------------------------------------------------------- VirtualProtect proc near push dword ptr [esp + 10h] push dword ptr [esp + 10h] lea eax, dword ptr [esp + 10h] push eax lea eax, dword ptr [esp + 10h] push eax push -1 xVirtualProtect label near mov eax, '!bgr' call eax ret 10h VirtualProtect endp map_page proc near push 1 pop ebx map_next label near push esi enter size _MEMORY_BASIC_INFORMATION, 0 mov eax, esp ;----------------------------------------------------------------------------- ;VirtualQuery(address, buffer, length) -> NtQueryVirtualMemory(-1, address, 0, buffer, length, &length) ;----------------------------------------------------------------------------- push eax push size _MEMORY_BASIC_INFORMATION push eax push 0 push esi push -1 xVirtualQuery label near mov eax, '!bgr' call eax cmp byte ptr [ebp + _MEMORY_BASIC_INFORMATION.mbiState - size _MEMORY_BASIC_INFORMATION + 1], MEM_COMMIT shr 8 je skip_commit push PAGE_READWRITE push MEM_COMMIT push ebx push esi call VirtualAlloc ;----------------------------------------------------------------------------- ;protect relocated page ;----------------------------------------------------------------------------- mov ecx, esp push ecx ;VirtualProtect push dword ptr [ebp + _MEMORY_BASIC_INFORMATION.mbiAllocationProtect - size _MEMORY_BASIC_INFORMATION] push ebx ;VirtualProtect push eax ;VirtualProtect ;----------------------------------------------------------------------------- ;unmap original page ;----------------------------------------------------------------------------- push ecx ;VirtualProtect push ebx ;PAGE_NOACCESS push ebx ;VirtualProtect mov esi, eax sub esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shVirtualAddress] add esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shName + 4] push esi ;VirtualProtect push edi ;----------------------------------------------------------------------------- ;map original page ;----------------------------------------------------------------------------- push ecx push PAGE_READONLY push ebx push esi xchg edi, eax call VirtualProtect ;----------------------------------------------------------------------------- ;insert page-level decompressor/decryptor here ;----------------------------------------------------------------------------- xor ecx, ecx mov ch, 4 rep movs dword ptr [edi], dword ptr [esi] pop edi call VirtualProtect call VirtualProtect skip_commit label near leave pop eax ;----------------------------------------------------------------------------- ;map in at least 16 bytes, to cover any XMM loads ;it's also enough to cover the largest possible legal instruction (15 bytes) ;----------------------------------------------------------------------------- lea esi, dword ptr [eax + 10h] and si, 0f000h cmp esi, eax jnbe map_next ret map_page endp code_reloc label near pop eax pop dword ptr [eax + (offset xVirtualQuery - offset apis_end) + 1] pop dword ptr [eax + (offset xVirtualProtect - offset apis_end) + 1] pop dword ptr [eax + (offset xVirtualAlloc - offset apis_end) + 1] pop esi mov cl, offset new_ki - offset ki call skip_code ki db 08Bh, 04Ch, 024h, 004h ;mov ecx, dword ptr [esp + 4] db 08Bh, 01Ch, 024h ;mov ebx, dword ptr [esp] db 051h ;push ecx db 053h ;push ebx db 0E8h ;call new_ki label near cmp dword ptr [ebx + erExceptionCode], STATUS_ACCESS_VIOLATION jne old_ki mov esi, dword ptr [ebx + erExceptionAddress] call find_secto xchg ecx, eax jecxz try_sectn ;----------------------------------------------------------------------------- ;attempted to access host image - redirect to relocated image ;----------------------------------------------------------------------------- sub esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shName + 4] add esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shVirtualAddress] mov dword ptr [eax + ctxEip], esi ret old_ki label near push '!bgr' busy_ret label near xchg ebx, eax ret host_num proc near push 'r' pop eax host_sect label near mov edi, '!bgr' ret host_num endp find_secto proc near call host_num find_sectol label near cmp dword ptr [edi + _IMAGE_SECTION_HEADER.shName - size _IMAGE_SECTION_HEADER], esi jbe secto_loop cmp dword ptr [edi + _IMAGE_SECTION_HEADER.shName + 4 - size _IMAGE_SECTION_HEADER], esi jbe secto_ret secto_loop label near sub edi, size _IMAGE_SECTION_HEADER dec eax jne find_sectol secto_ret label near ret find_secto endp find_sectn proc near call host_num find_sectnl label near cmp dword ptr [edi + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER], esi jbe sectn_loop cmp dword ptr [edi + _IMAGE_SECTION_HEADER.shVirtualAddress - size _IMAGE_SECTION_HEADER], esi jbe sectn_ret sectn_loop label near sub edi, size _IMAGE_SECTION_HEADER dec eax jne find_sectnl sectn_ret label near ret find_sectn endp try_sectn label near push ebx push esi call find_sectn xchg ecx, eax jecxz check_inst call map_page ;----------------------------------------------------------------------------- ;if the exception address matches the exception parameter, ;then exception was caused by eip value and we are done ;----------------------------------------------------------------------------- check_inst label near pop ebp pop eax mov esi, dword ptr [eax + erExceptionInformation] cmp esi, ebp je busy_ret ;----------------------------------------------------------------------------- ;otherwise, exception was caused by memory access ;that can be host memory or unmapped relocated memory ;or it could be a bug in the host, and we skip that case ;----------------------------------------------------------------------------- find_inst label near inc esi je old_ki dec esi call find_sectn test eax, eax jne found_inst call find_secto xchg ecx, eax jecxz old_ki sub esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shName + 4] add esi, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shVirtualAddress] ;----------------------------------------------------------------------------- ;we reach here if memory access is in host memory or unmapped relocated memory ;we must examine the instruction and turn it into an absolute memory reference ;because we cannot alter any registers ;----------------------------------------------------------------------------- found_inst label near push esi call map_page pop esi busy_flag label near clc jb busy_ret mov bl, ctxEsp xchg ebp, esi ;----------------------------------------------------------------------------- ;point to next instruction, assuming that it's not a call or jump ;----------------------------------------------------------------------------- call get_opsize inst_delta label near mov edi, dword ptr [esp - 4] lea edi, dword ptr [edi + ebx + (offset inst_buff - offset inst_delta) - ctxEsp] mov ecx, dword ptr [esp + 8] add ecx, ebx add dword ptr [ecx + ctxEip - ctxEsp], eax xchg ebx, eax lea edx, dword ptr [ecx + ctxEcx - ctxEsp] mov dword ptr [edi + offset restore_ctx - offset inst_buff + 2], edx lea edx, dword ptr [edi + offset restore_ctx - offset inst_buff - 1] ;----------------------------------------------------------------------------- ;copy all prefixes and first byte of real instruction ;no critical section because no thread switch can occur ;----------------------------------------------------------------------------- copy_inst label near dec ebx lods byte ptr [edi] stos byte ptr [edi] cmp al, 0f0h je copy_inst mov ah, al sub al, 64h cmp al, 3 jbe copy_inst sub al, 0f2h - 64h cmp al, 1 jbe copy_inst and ah, 0e7h cmp ah, 26h je copy_inst ;----------------------------------------------------------------------------- ;copy next byte if 0f ;----------------------------------------------------------------------------- cmp al, 0fh - 0f2h jne check_moveax dec ebx movs byte ptr [edi], byte ptr [esi] check_moveax label near sub al, 0a0h - 0f2h ;----------------------------------------------------------------------------- ;check for a0-a3 (mov to/from al/eax), a4-a7 (movs/cmps), aa-af (stos/lods/scas) ;----------------------------------------------------------------------------- cmp al, 0fh jnbe check_calljmp ;----------------------------------------------------------------------------- ;check for a0-a3 (mov to/from al/eax) because they don't have any modr/m byte ;----------------------------------------------------------------------------- cmp al, 3 jbe inst_eax push ebx push ebx xchg ebx, eax pushad push 2 pop ebp ;----------------------------------------------------------------------------- ;for strings, we have to change the registers temporarily ;so find and map esi and edi if possible ;----------------------------------------------------------------------------- find_str label near push ecx mov esi, dword ptr [ecx + ctxEdi - ctxEsp] call find_sectn test eax, eax jne map_str call find_secto xchg ecx, eax jecxz skip_map mov ecx, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shVirtualAddress] sub ecx, dword ptr [(edi - size _IMAGE_SECTION_HEADER) + _IMAGE_SECTION_HEADER.shName + 4] add esi, ecx mov dword ptr [eax + ctxEdi - ctxEsp], esi mov dword ptr [ebp * 4 + esp + 20h], ecx map_str label near call map_page skip_map label near pop ecx add ecx, 4 dec ebp jne find_str popad mov ah, offset skip_stack - offset xchg_stack1 jmp inst_str ;----------------------------------------------------------------------------- ;save return address on original stack ;----------------------------------------------------------------------------- call_inst label near xchg dword ptr [ecx + ctxEsp - ctxEsp], esp push dword ptr [ecx + ctxEip - ctxEsp] xchg dword ptr [ecx + ctxEsp - ctxEsp], esp jump_inst label near mov eax, dword ptr [ebp] mov dword ptr [ecx + ctxEip - ctxEsp], eax xchg ebx, eax ret ;----------------------------------------------------------------------------- ;call and jump indirect are a special case ;because we can't execute them directly ;----------------------------------------------------------------------------- check_calljmp label near mov ah, al mov al, byte ptr [esi] and al, 38h cmp ax, ((0ffh - 0a0h) shl 8) + 20h je jump_inst cmp ax, ((0ffh - 0a0h) shl 8) + 10h je call_inst ;----------------------------------------------------------------------------- ;everything else has modr/m byte replaced by absolute memory reference ;----------------------------------------------------------------------------- or al, 5 stos byte ptr [edi] dec ebx lods byte ptr [esi] and al, 0c7h mov ah, al and al, 7 cmp al, 4 jne skip_sib dec ebx lods byte ptr [esi] test ah, 0c0h jne skip_sib and al, 7 mov ah, al skip_sib label near cmp ah, 5 jne skip_abs inst_eax label near mov ah, 80h skip_abs label near add eax, eax shr ax, 1 shr eax, 0eh sub ebx, eax add esi, eax xchg ebp, eax stos dword ptr [edi] xchg ebx, eax xchg ecx, eax rep movs byte ptr [edi], byte ptr [esi] xchg ecx, eax mov al, offset parse_xchg - offset rest_str ;----------------------------------------------------------------------------- ;set the busy flag to prevent re-entry ;and enable or disable the stack swapping ;this is because string instructions can cause additional faults ;but if the stack was the original value then the second context will overwrite the first one ;so it is necessary to not change the stack value (it's not needed by the instruction anyway) ;however, it must be possible to change the stack in other cases, to allow eg mov esp, [mem] ;----------------------------------------------------------------------------- inst_str label near inc byte ptr [edx + (offset busy_flag - offset restore_ctx) + 1] mov byte ptr [edx + (offset jmp_stack1 - offset restore_ctx) + 2], ah mov byte ptr [edx + (offset jmp_stack2 - offset restore_ctx) + 2], ah mov byte ptr [edx + (offset jmp_rest - offset restore_ctx) + 2], al mov al, 0ebh stos byte ptr [edi] mov eax, edx sub eax, edi stos byte ptr [edi] ;----------------------------------------------------------------------------- ;swap context, need to save only some registers ;----------------------------------------------------------------------------- pushfd push dword ptr [ecx + ctxEFlags - ctxEsp] popfd jmp_stack1 label near jmp xchg_stack1 xchg_stack1 label near xchg dword ptr [ecx + ctxEsp - ctxEsp], esp skip_stack label near mov edi, dword ptr [ecx + ctxEdi - ctxEsp] mov esi, dword ptr [ecx + ctxEsi - ctxEsp] mov ebx, dword ptr [ecx + ctxEbx - ctxEsp] xchg dword ptr [ecx + ctxEdx - ctxEsp], edx mov eax, dword ptr [ecx + ctxEax - ctxEsp] mov ebp, dword ptr [ecx + ctxEbp - ctxEsp] xchg dword ptr [ecx + ctxEcx - ctxEsp], ecx ;----------------------------------------------------------------------------- ;execute the instruction ;jump is appended to skip rest of buffer and reach restore_ctx ;----------------------------------------------------------------------------- inst_buff db "BASLR - roy g biv" ;must be exactly 11h bytes long ;----------------------------------------------------------------------------- ;swap context back ;----------------------------------------------------------------------------- restore_ctx label near xchg dword ptr [offset $], ecx jmp_stack2 label near jmp xchg_stack2 xchg_stack2 label near xchg dword ptr [ecx + ctxEsp - ctxEsp], esp pushfd pop dword ptr [ecx + ctxEFlags - ctxEsp] popfd mov dword ptr [ecx + ctxEdi - ctxEsp], edi mov dword ptr [ecx + ctxEsi - ctxEsp], esi mov dword ptr [ecx + ctxEbx - ctxEsp], ebx xchg dword ptr [ecx + ctxEdx - ctxEsp], edx mov dword ptr [ecx + ctxEax - ctxEsp], eax mov dword ptr [ecx + ctxEbp - ctxEsp], ebp dec byte ptr [edx + (offset busy_flag - offset restore_ctx) + 1] jmp_rest label near jmp parse_xchg ;----------------------------------------------------------------------------- ;if we changed the registers for strings, then we must undo the changes ;----------------------------------------------------------------------------- rest_str label near pop eax sub dword ptr [ecx + ctxEsi - ctxEsp], eax pop eax sub dword ptr [ecx + ctxEdi - ctxEsp], eax parse_xchg label near mov al, 1 parse_ret label near ret skip_code label near pop edi repe cmps byte ptr [edi], byte ptr [esi] jne parse_ret ;----------------------------------------------------------------------------- ;write enable the call ;----------------------------------------------------------------------------- push eax push esp push PAGE_READWRITE push 4 push esi call VirtualProtect ;----------------------------------------------------------------------------- ;replace the call ;----------------------------------------------------------------------------- push esi lods dword ptr [esi] add eax, esi mov dword ptr [edi + (offset old_ki - offset new_ki) + 1], eax mov eax, edi sub eax, esi pop esi mov dword ptr [esi], eax pop eax ;----------------------------------------------------------------------------- ;restore previous protection ;----------------------------------------------------------------------------- push eax push esp push eax push 4 push esi call VirtualProtect ;----------------------------------------------------------------------------- ;get some information about the PE header ;because we will make a local copy of the section table ;----------------------------------------------------------------------------- mov eax, dword ptr fs:[tebProcessEnvironmentBlock] mov eax, dword ptr [eax + pebImageBaseAddress] add eax, dword ptr [eax + e_lfanew] movzx ecx, byte ptr [eax + _IMAGE_NT_HEADERS.nthFileHeader.fhNumberOfSections] mov byte ptr [edi + (offset host_num - offset new_ki) + 1], cl movzx esi, word ptr [eax + _IMAGE_NT_HEADERS.nthFileHeader.fhSizeOfOptionalHeader] lea esi, dword ptr [eax + esi + _IMAGE_NT_HEADERS.nthOptionalHeader] push dword ptr [eax + ohImageBase] imul ebp, ecx, size _IMAGE_SECTION_HEADER push PAGE_EXECUTE_READWRITE push MEM_COMMIT push ebp push 0 call VirtualAlloc push eax mov ecx, ebp xchg edi, eax rep movs byte ptr [edi], byte ptr [esi] mov dword ptr [eax + (offset host_sect - offset new_ki) + 1], edi pop edi pop esi ;----------------------------------------------------------------------------- ;convert from section attributes to memory protection value ;----------------------------------------------------------------------------- alloc_sects label near movzx eax, byte ptr [ebp + edi - 1] shr al, 5 call skip_xlat db 0, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ, PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE skip_xlat label near pop ebx xlat byte ptr [ebx] mov ebx, dword ptr [ebp + edi + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER] push esp ;VirtualProtect push PAGE_NOACCESS ;VirtualProtect push ebx ;VirtualProtect push eax push MEM_RESERVE ;----------------------------------------------------------------------------- ;enlarge by random amount to ensure non-sequential addresses ;----------------------------------------------------------------------------- rdtsc and eax, 3000h ;from 0 to 12kb add eax, ebx push eax push 0 call VirtualAlloc lea ecx, dword ptr [eax + ebx] mov dword ptr [ebp + edi + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER], ecx xchg dword ptr [ebp + edi + _IMAGE_SECTION_HEADER.shVirtualAddress - size _IMAGE_SECTION_HEADER], eax add eax, esi mov dword ptr [ebp + edi + _IMAGE_SECTION_HEADER.shName + 4 - size _IMAGE_SECTION_HEADER], eax push eax add eax, ebx mov dword ptr [ebp + edi + _IMAGE_SECTION_HEADER.shName - size _IMAGE_SECTION_HEADER], eax ;----------------------------------------------------------------------------- ;unmap host pages - cannot be dumped anymore ;----------------------------------------------------------------------------- call VirtualProtect sub ebp, size _IMAGE_SECTION_HEADER jne alloc_sects pop eax ret db "01/02/08" include rgblde.asm skip_apis label near pop edi ;----------------------------------------------------------------------------- ;parse export table ;----------------------------------------------------------------------------- mov esi, dword ptr [ebx + esi + IMAGE_DIRECTORY_ENTRY_EXPORT] lea esi, dword ptr [ebx + esi + edAddressOfFunctions] lods dword ptr [esi] ;Export Address Table RVA lea edx, dword ptr [ebx + eax] lods dword ptr [esi] ;Name Pointer Table RVA lea ecx, dword ptr [ebx + eax] lods dword ptr [esi] ;Ordinal Table RVA lea ebp, dword ptr [ebx + eax] mov esi, ecx push_export label near push ecx get_export label near lods dword ptr [esi] push ebx add ebx, eax ;Name Pointer VA or eax, -1 crc_outer label near xor al, byte ptr [ebx] push 8 pop ecx crc_inner label near add eax, eax jnb crc_skip xor eax, 4c11db7h ;use generator polymonial (see IEEE 802) crc_skip label near loop crc_inner sub cl, byte ptr [ebx] ;carry set if not zero inc ebx ;carry not altered by inc jb crc_outer pop ebx cmp dword ptr [edi], eax jne get_export ;----------------------------------------------------------------------------- ;exports must be sorted alphabetically, otherwise GetProcAddress() would fail ;this allows to push addresses onto the stack, and the order is known ;----------------------------------------------------------------------------- pop ecx mov eax, esi sub eax, ecx ;Name Pointer Table VA shr eax, 1 movzx eax, word ptr [ebp + eax - 2] ;get export ordinal mov eax, dword ptr [eax * 4 + edx] ;get export RVA add eax, ebx push eax scas dword ptr [edi] cmp dword ptr [edi], 0 jne push_export push 0 mov eax, esp push 1 mov ecx, esp push PAGE_EXECUTE_READWRITE push MEM_COMMIT push ecx push 0 push eax push -1 call dword ptr [eax + 0ch] pop ecx pop eax push eax mov cx, offset skip_apis - offset apis_end mov esi, edi mov edi, eax ife (offset code_reloc - offset apis_end) and 0ffffff00h mov al, offset code_reloc - offset apis_end else mov ax, offset code_reloc - offset apis_end endif rep movsb jmp eax baslr_end label near .code code_begin label near call GetCommandLineW xor edi, edi dec di mov ebp, dword ptr [eax] and ebp, edi cmp ebp, '"' ;Unicode-compatible compare je skip_argv0 push ' ' pop ebp skip_argv0 label near push eax call CharNextW mov ecx, dword ptr [eax] and ecx, edi je skip_argv1 cmp ecx, ebp jne skip_argv0 find_argv1 label near push eax call CharNextW mov ecx, dword ptr [eax] and ecx, edi cmp ecx, ' ' ;Unicode-compatible compare je find_argv1 skip_argv1 label near xor edi, edi test ecx, ecx je print_usage push edi push edi push OPEN_EXISTING push edi push edi push GENERIC_READ or GENERIC_WRITE push eax call CreateFileW push eax inc eax je print_usage dec eax push eax ;ReadFile mov ecx, esp push edi ;ReadFile push esp ;ReadFile push 4 ;ReadFile push ecx ;ReadFile push eax push edi push edi push e_lfanew push eax xchg ebx, eax call SetFilePointer call ReadFile pop esi enter size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER, 0 mov eax, esp push edi ;WriteFile push esp ;WriteFile push size _IMAGE_NT_HEADERS ;WriteFile push eax ;WriteFile push ebx ;WriteFile push edi ;SetFilePointer push edi ;SetFilePointer push esi ;SetFilePointer push ebx ;SetFilePointer push edi ;ReadFile push esp ;ReadFile push size _IMAGE_NT_HEADERS ;ReadFile push eax ;ReadFile push ebx ;ReadFile push edi push edi push esi push ebx call SetFilePointer call ReadFile movzx eax, word ptr [ebp + _IMAGE_NT_HEADERS.nthFileHeader.fhNumberOfSections - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)] dec eax imul eax, eax, size _IMAGE_SECTION_HEADER movzx ecx, word ptr [ebp + _IMAGE_NT_HEADERS.nthFileHeader.fhSizeOfOptionalHeader - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)] lea eax, dword ptr [ecx + eax + _IMAGE_NT_HEADERS.nthOptionalHeader] add eax, esi lea ecx, dword ptr [ebp - size _IMAGE_SECTION_HEADER] mov esi, offset baslr_end - offset baslr_begin push edi ;WriteFile push esp ;WriteFile push size _IMAGE_SECTION_HEADER ;WriteFile push ecx ;WriteFile push ebx ;WriteFile push edi ;SetFilePointer push edi ;SetFilePointer push eax ;SetFilePointer push ebx ;SetFilePointer push edi ;ReadFile push esp ;ReadFile push size _IMAGE_SECTION_HEADER ;ReadFile push ecx ;ReadFile push ebx ;ReadFile push edi push edi push eax push ebx call SetFilePointer call ReadFile push edi ;WriteFile push esp ;WriteFile push esi ;WriteFile push offset baslr_begin ;WriteFile push ebx ;WriteFile push edi push edi mov eax, dword ptr [ebp + _IMAGE_SECTION_HEADER.shVirtualAddress - size _IMAGE_SECTION_HEADER] mov edx, dword ptr [ebp + _IMAGE_SECTION_HEADER.shSizeOfRawData - size _IMAGE_SECTION_HEADER] lea ecx, dword ptr [eax + edx] xchg dword ptr [ebp + _IMAGE_NT_HEADERS.nthOptionalHeader.ohAddressOfEntryPoint - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)], ecx add ecx, dword ptr [ebp + _IMAGE_NT_HEADERS.nthOptionalHeader.ohImageBasex - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)] mov dword ptr [offset baslr_begin + 1], ecx mov ecx, dword ptr [ebp + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER] inc ecx loop skip_raw mov dword ptr [ebp + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER], edx mov ecx, edx skip_raw label near add edx, dword ptr [ebp + _IMAGE_SECTION_HEADER.shPointerToRawData - size _IMAGE_SECTION_HEADER] push edx push ebx add dword ptr [ebp + _IMAGE_SECTION_HEADER.shSizeOfRawData - size _IMAGE_SECTION_HEADER], esi add esi, ecx mov ecx, dword ptr [ebp + _IMAGE_NT_HEADERS.nthOptionalHeader.ohSectionAlignment - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)] lea esi, dword ptr [esi + ecx - 1] neg ecx and esi, ecx mov dword ptr [ebp + _IMAGE_SECTION_HEADER.shVirtualSize - size _IMAGE_SECTION_HEADER], esi add eax, esi mov dword ptr [ebp + _IMAGE_NT_HEADERS.nthOptionalHeader.ohSizeOfImage - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)], eax xor eax, eax mov dword ptr [ebp + _IMAGE_NT_HEADERS.nthOptionalHeader.ohCheckSum - (size _IMAGE_NT_HEADERS + size _IMAGE_SECTION_HEADER)], eax call SetFilePointer call WriteFile call SetFilePointer call WriteFile call SetFilePointer call WriteFile leave call CloseHandle push offset protect_e - offset protect pop eax mov ecx, offset protect jmp print_msg print_usage label near push offset usage_e - offset usage pop eax mov ecx, offset usage print_msg label near push edi push esp push eax push ecx push -0ch call WriteFile call ExitProcess protect db "protect okay!", 0ah protect_e label near usage db "usage: baslr <filename>", 0ah usage_e label near end code_begin